package base.thread_JUC.demo01;


import java.util.concurrent.TimeUnit;

/**
 * volatile 只能保证内存可见性演示。
 * https://blog.csdn.net/u012988901/article/details/111143941
 * 主存：堆内存
 * 线程Tn：工作内存拷贝自主存
 * CPU：只与L1/L2/L3级缓存打交道，内存数据拷贝进缓存，cpu读取的是缓存内容。
 * 强制刷新：内存内容刷新到缓存的过程。
 */
public class Client1 {

    public static void main(String[] args) {
        RunnableDemo runnableDemo = new RunnableDemo();


        new Thread(runnableDemo, "t1").start();

        /** main线程对t1线程中runnableDemo对象的改变是不可见的。
         * JMM：Java内存模型，t1线程执行，会拷贝一份runnableDemo共享变量到自己线程内存中（工作内存）,t1完成后，结果写回主存。
         * 由于，t1线程睡眠2s，因此main线程while(true)已经循环起来，因while(true)底层非常快，导致连t1写回主存的数据main线程都来不及
         * 读取，main线程一直使用之前的flag=false，因此这个程序出现僵死，可以将while循环里面sout一下，就可以让main线程有机会读到t1写回
         * 的flag=true，从而退出僵死。
         * 但是还有一种更好的优化方式，用volatile 修饰 flag 即可。volatile 修饰的变量对所有线程都可见。while内部用到volatile修饰的变量
         * 每次会强制从主内存中读取。从而获取到最新flag值，此时，flag=true退出循环。
         */
        while (true){
            /**
             * println 办法因为最终会调用 FileOutputStream.writeBytes 这个 native 办法，所以无奈被内联优化（inling）。
             * 而被内联的方法调用从编译器的角度看是一个“full memory kill”，也就是说副作用不明 、必须对内存的读写操作做激进解决。
             *
             * 在这个例子里，下一轮循环要在上一轮循环的 println 之后。这里“激进解决”为：就算上一轮我曾经读取了 flag 的值，
             * 因为通过了一个副作用不明的中央，再到下一次拜访就必须从新读取了
             */
            //System.out.println("wait......"+runnableDemo.isFlag());// println方法
//            JIT 优化提升
//            boolean flag = runnableDemo.isFlag();
//            if(flag){
            if(runnableDemo.isFlag()){
                break;
            }
        }
    }
}

class RunnableDemo implements Runnable{

    private volatile boolean flag = false;

    @Override
    public void run() {
        try {
            TimeUnit.SECONDS.sleep(2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        flag = true;
        System.out.println("flag--------------->"+flag);
    }

    public boolean isFlag() {
        return flag;
    }

    public void setFlag(boolean flag) {
        this.flag = flag;
    }
}
